MagnaMedia · AMIGA-Magazin · Intuition-Programmierung unter p.OS, Folge 3

Aktuelles Heft 9/97

Intuitive Benutzeroberfl�chen


Im dritten und letzten Kursteil der p.OS-Programmierung werden wir das Kapitel Intuition unter p.OS mit den Men�s und dem EasyRequester abschlie�en. Zum besseren Verst�ndnis werden wir nat�rlich unser Beispielprogramm aus den vorangegangenen Teilen wieder erweitern. Es wird dann kein Problem mehr f�r Sie sein, Programme unter p.OS zu entwickeln.

# von Michael Christoph

Da Ihnen p.OS die meisten Aufgaben beim Erstellen der Oberfl�che abnimmt (Fontsensitiv, Men�layout, Gadgetpositionierung, Windowresizing, ...), k�nnen Sie sich ganz der Implementierung der gew�nschten Aufgaben widmen. Unser Beispielprogramm wird Sie dabei zus�tzlich unterst�tzen, indem Sie ben�tigte Programmteile (Gadgets/ Men�s/Messageloop/...) einfach per Cut-Copy-Paste �bernehmen.

Beachten Sie dabei aber stets, da� f�r alle verwendeten Funktionen die entsprechenden Betriebsystem-Libraries und -Devices ge�ffnet sein m�ssen. Diese sind am Programmende dann wieder alle zu schlie�en. Beachten Sie auch, da� im Fehlerfall ein kontrollierter Programmabbruch stattfinden mu�, bei dem alle reservieren Resourcen wieder freizugeben sind. Im Fehlerfall mu� auch immer eine Mitteilung an den Benutzer erfolgen (z.B. per pOS_ PrintDosErr() oder pOS_ SPrintf()). Auch bei einem Workbenchstart unter p.OS d�rfen Sie die pDOS-Ausgabefunktionen benutzen.

Im Bedarfsfall wird ein Console-Fenster zur Ausgabe ge�ffnet. Bei Oberfl�chen-Programmen empfiehlt es sich aber, den Fehler �ber Requester (z.B. pOS_EasyRequest Args()) anzuzeigen. Die Fehlertexte sollten dabei f�r jederman verst�ndlich und ausf�hrlich sein. Statt �Lock failed� verwenden Sie besser �Datei %s ist nicht zu finden.�.
Dabei sollte auch der (vollst�ndige) Dateiname angegeben werden. Falls Sie zus�tzliche Informationen bei einer Fehlermeldung w�nschen, k�nnen Sie z.B. einen programmspezifischen Fehlercode in Klammern mit ausgeben lassen. Beachten Sie, da� im Fehlerfall unerfahrene Benutzer meist nur den halben Fehlertext, ohne weitere Angaben, wiedergeben k�nnen. Erfahrene User werden bei ausf�hrlichen Fehlertexten den Fehler meist selbst�ndig beheben.

Auf die ANSI-Funktionen exit()/atexit()/abort() mu� im Fehlerfall unbedingt verzichtet werden, da diese intern auf Amiga-Funktionen zur�ckgreifen, was unweigerlich zu einem Programmfehler f�hrt. In Zukunft wird Ihnen daf�r die Funktion pOS_ExitProcess() zur Verf�gung stehen. Es ist aber immer besser, wenn die Programme (und auch die Funktionen) nur einen Ausstiegspunkt (eine Return-Anweisung) enthalten und dadurch auf harten Programmausstieg verzichten. Jedes Programm (zumindest bei strukturierten Programmiersprachen wie C oder C++) l��t sich so entwickeln, da� diese Bedingung zutrifft. C++ (Version 3) bietet hierzu auch das Exception-Handling an.
Damit ist es sehr einfach, aus jeder tiefen Unterfunktion wieder zu einem kontrollierbaren Punkt zur�ckzukehren. Nach M�glichkeit sollte das Programm nach der Fehlermeldung (evtl. auf Benutzerwunsch) weiterlaufen.

Programmprojekt unter p.OS: Unser selbstgestaltetes Fenster hat noch ein Men� bekommen
Sie k�nnen z.B. in der main()-Routine nur die Argumente parsen, die Libraries �ffnen und alles weitere von einer Unterfunktion erledigen lassen. Diese kehrt erst am Programmende oder im Fehlerfall (mit dem Shell-Fail-Code) zur�ck. Danach werden die Libraries geschlossen und das Programm �ber die main()-Routine beendet. Dabei k�nnen Sie der aufrufenden Shell noch einen Returncode zur�ckgeben.Das erreichen Sie �ber die Funktion pOS_SetShellFail(). Vordefinierte Fail-Werte in "p:pDOS/DosErrors.h" sind:

 
- DOSFAIL_OK     (0) : Programm wurde fehlerlos abgearbeitet
- DOSFAIL_WARN   (5) : Warnung, z.B. bei fehlerhaften Parametern
- DOSFAIL_ABORT  (8) : Benutzerabbruch durch CTRL-C
- DOSFAIL_ERROR (10) : einfacher Fehler
- DOSFAIL_FAIL  (20) : gro�er Fehler, z.B. Speichermangel

Bei Bedarf k�nnen Sie auch programmspezifische Fehlercodes setzen, die ab �21� beginnen d�rfen. Normalerweise ist das aber nicht notwendig. Die Shell kann in Scripts auch auf den Returncode reagieren. Die Funktion �IF� erm�glicht eine Unterscheidung zwischen Warn/Error/Fail (z.B. nur nach korrekter Diskettenformatierung werden Daten kopiert).
Nach diesem Ausflug ins p.OS-StyleGuide wenden wir uns nun den p.OS-Men�s zu. Der erste sichtbare Unterschied zum AmigaOS: die Men�s werden nicht mehr in der Bildschirmtitelzeile angezeigt, sondern auf der Titelzeile des zugeh�rigen Fensters. Die Anordnung wird sp�ter evtl. frei w�hlbar sein, was aber auf die Programmierung der Men�s keinen Einflu� hat.

Der zweite Punkt, der nur wenigen Anwendern auffallen wird, ist, da� das Window w�hrend der Men�auswahl nicht mehr gesperrt ist. Dadurch entf�llt eine m�gliche Deadlock-Situation, wie sie beim Amiga auftreten k�nnte.
Die Men�struktur wird, �hnlich den Gadgets, nur beschrieben. Die Men�anordnung und Positionierung �bernimmt das OS wieder vollst�ndig f�r Sie. Die Men�eintr�ge sind wiederum Objekte, wodurch auch Grafiken und Animationen als Eintr�ge kein Problem sind. Die Men�struktur finden Sie in �p:pIntui/Menu.h�. Interessant sind hierbei mt_Type f�r Title/Item/Sub, mt_Lable f�r den Texteintrag und mt_CommKey f�r einen Shortkey. Seltener ben�tigt werden mt_Flags (z.B. zum Abhaken) und mt_MutualExclude (f�r Ausschlu�punkte). Die angesprochenen Grafiken und Animationen bekommen Sie ins Men� �ber eine IntuiObj-Beschreibung in mt_Tags. Das Ende der Men�beschreibung wird per mt_Type MENUTAGTYP_End abgeschlossen.

 
Kurs�bersicht
Dieser dreiteilige Programmierkurs soll die Konzepte zur Entwicklung von GUIs (Graphical User Interfaces = Grafische Benutzeroberfl�chen) unter pOS vorstellen. Begleitend wird stufenweise ein einfaches Programm entwickelt, um auch die praktische Seite nicht zu vernachl�ssigen.

Folge 1: Beschreibung des pIntui-Konzepts, Beispielprogramm mit Fenster �ffnen und leerem Messageloop Am Ende dieses ersten Teils haben Sie ein Programmger�st, das die �bergebenen Argumente parsen kann, ein Fenster �ffnet und auf das Anklicken des Schlie�-Symbols wartet. Dieses Programmger�st k�nnen Sie als Ausgangsbasis f�r jedes neue Programm verwenden.

Folge 2: Beschreibung von Gadget/IObject-Konzept von pOS und BubbleHelp, Beispielprogramm erweitert um Gadgets und Messageloop. Im zweiten Kursteil wird das Fenster lebendig, d.h. wir werden es mit vielen verschiedenen Gadgettypen f�llen. Dazu wird das Gadgetkonzept von pOS n�her beleuchtet, die einzelnen Gadget-Tags vorgestellt und der Messageloop um die Gadgetinterkommunikation erweitert.

Folge 3: Beschreibung von Men�aufbau/auswertung und Requestern Beispielprogramm erweitert um Men�s, EasyRequester und Messageloop Im dritten und letzten Kursteil erh�lt das Fenster noch ein Men� spendiert und nat�rlich wird der Messageloop nochmals um die Men�verwaltung erweitert. Zus�tzlich wird ein Easy-Requester f�r die Programminformation erg�nzt.
Beachten Sie, da� unter p.OS zwischen Item- und Sub-Trennlinien unterschieden wird. Die Menu-Flags setzen sich wie folgt zusammen: Bei normalen Auswahlpunkten wird hier 0 eingetragen. Soll der Men�punkt aktivierbar sein, l��t sich der per MENUITF_Hook bestimmen. Bei Auswahl wird der Punkt mit einem vorangestellten Haken ausgestattet.

Mit MENUITF_Toggle wird bei jeder Auswahl der Hakenzustand gewechselt. Ob ein Punkt aktiviert ist, k�nnen Sie beim Start �ber MENUTIF_ IsChecked festlegen. Die W�hlbarkeit definiert man �ber MENUITF_Disabled (gesetzt = nicht w�hlbar).
Einer Erkl�rung bedarf noch der Eintrag f�r mt_MutualExclude. Die Funktionsweise ist �hnlich den MX-Gadgets. Bei der Auswahl eines Men�punktes bestimmt die Maske in mt_MutualExclude, welche anderen Men�punkte auszuschalten sind.
Es lassen sich nur die Eintr�ge der aktuellen Men�ebene beeinflussen. Dabei werden maximal die ersten 32 Eintr�ge beeinflu�t (32 Bits im ULONG). Besser verdeutlichen l��t sich das an einem Beispiel, etwa die Style-Auswahl f�r eine Schrift. Hierbei kann entweder Plain oder eine Kombination aus Bold, Italic und Underline auftreten. Dabei ist bei der Auswahl von Plain immer dieser Punkt abzuhaken, alle anderen mu� man deaktivieren. Die anderen drei Punkte k�nnen einzeln ein- und ausgeschaltet werden. Aus dieser Anforderung ergibt sich folgende Men�beschreibung:

 
mt_Lable         = "Plain"
mt_Flags         = MENUITF_Hook | MENUITF_IsChecked
mt_MutualExclude = 0x0E   /* %00001110 => B/I/U ausschalten */
mt_Lable         = "Bold"
mt_Flags         = MENUITF_Hook | MENUITF_Toggle
mt_MutualExclude = 0x01   /* %00000001 => Plain aus */
mt_Lable         = "Italic"
mt_Flags         = MENUITF_Hook | MENUITF_Toggle
mt_MutualExclude = 0x01   /* %00000001 => Plain aus */
mt_Lable         = "Underline"
mt_Flags         = MENUITF_Hook | MENUITF_Toggle
mt_MutualExclude = 0x01   /* %00000001 => Plain aus */

Der Eintrag Plain ist beim Start abgehakt und besitzt kein Toggle-Flag, um diesen Punkt bei mehrfacher Auswahl von Plain nicht zu deaktiveren, wodurch kein Punkt mehr aktiv w�re. Es gibt aber trotzdem eine Situation, die das OS nicht abfangen kann. W�hlen Sie z.B. Bold, wird der Punkt abgehakt und Plain deaktiviert. Bei der zweiten Auswahl von Bold wird der Punkt wieder deaktivert und keiner der vier Punkte ist mehr gesetzt. Diesen Fall m�ssen Sie zwangsl�ufig selbst im Messageloop abfangen (vereinfachte Darstellung):

 
if(
pOS_GetWindowMenuChecker(0)==FALSE     &&
pOS_GetWindowMenuChecker(1)==FALSE     &&
pOS_GetWindowMenuChecker(2)==FALSE     &&
pOS_GetWindowMenuChecker(3)==FALSE)
pOS_SetWindowMenuChecker(0,TRUE);

Einfacher w�re die Aufgabe, wenn ein Punkt immer alle anderen ausschlie�en w�rde: In diesem Fall geben Sie f�r jeden Punkt nur das Hook-Flag an. Dadurch wird bei doppelter Auswahl desselben Punktes kein Toggle durchgef�hrt und der Punkt bleibt weiterhin angew�hlt. Die vier MutualExclude-Eintr�ge lauten dann:

 
0x0E   /* %00001110 */
0x0D   /* %00001101 */
0x0B   /* %00001011 */
0x07   /* %00000111 */

Die Maske l��t sich, wie bereits erw�hnt, auf die ersten 32 Men�eintr�ge ausdehnen. Beachten Sie, da� Trennlinien auch einen Eintrag darstellen, der nicht beeinflu�bar ist und daher in der Maske durch eine 0 angezeigt werden sollte.
Die MX-Gadgets arbeiten intern nach demselben Schema. Allerdings ist hier die �nur einer aktiv�-Schaltung vorgegeben. Ein anderes Verhalten k�nnen Sie �ber ICLTAG_ MutualExclude als Maske �bergeben.
Zur Laufzeit kann der Aktivierungszustand/W�hlbarkeit �ber pOS_MenuItem->mi_ Flags ermittelt werden. Zum �ndern existieren die Funktionen pOS_SetWindowMenuChecker() und pOS_EnableWindowMenu(). Die dabei ben�tigte pOS_MenuNum setzen Sie wie folgt zusammen: Entweder tragen Sie den Wert als ULONG oder die drei Einzelkomponenten als UBYTEs ein. Die Punkte werden jeweils ab 0 gez�hlt und k�nnen theoretisch bis maximal 254 laufen. Die Zahl 255 (= 0xFF) hat eine Sonderstellung und bedeutet, da� dieser Eintrag nicht beachtet werden soll (wenn beispielsweise kein Sub-Men� existiert).

Die Men�nummern f�r das zweite Men�, dritter Eintrag (kein Sub) w�rde sich somit aus

 
pOS_MenuNum->men_U.men_Pck[MENNUPCK_Title] = 1
pOS_MenuNum->men_U.men_Pck[MENNUPCK_Item]  = 2
pOS_MenuNum->men_U.men_Pck[MENNUPCK_Sub]   = 0xFF

oder aus

 
pOS_MenuNum->men_U.men_Num = 0x0102FF00

zusammensetzen. �ber diese Men�nummern k�nnen Sie auch die Adresse des Men�eintrags per pOS_GetMenuItemFromNum() ermitteln. �ber pOS_CreateMenuTagA() erzeugen Sie aus der Men�beschreibung die interne Men�struktur, die noch �ber pOS_PreLayoutMenu() vorbereitet werden mu�. Danach kann sie bei Bedarf per pOS_SetMenuStrip() in das zugeh�rige Fenster eingeh�ngt werden. Verwenden Sie mehrere Fenster, sollte das Men� in jedem Fenster verf�gbar sein. Dabei d�rfen Sie den einen Men�zeiger in mehreren Fenstern verwenden. Am Programmende ist die interne Men�struktur mit pOS_DeleteMenu() freizugeben.

Nach der Men�auswahl sendet Intuition eine IDCMP_ MenuPick-Message. Dabei ist 9 im_Code-Feld die gew�hlte Men�nummer vermerkt. Die Men�verteilung kann wieder mit einer verschachtelten Switch-Case-Konstellation ausgewertet werden. Bedenken Sie, da� der erste Eintrag immer 0 lautet. Alternativ k�nnen Sie statt der Zahlen auch auf Defines oder Enumerations zur�ckgreifen, um auch nach Men�umbauten keine gro�en �nderungen im Messagelloop durchf�hren zu m�ssen. Eine andere M�glichkeit ist, im User-Zeiger des Men�s eine Funktions-Adresse abzulegen, die man nur noch aufrufen mu�.
Das p.OS-StyleGuide schreibt vor, da� Men�punkt-Shortcuts, im Gegensatz zu Gadgets, nicht lokalisiert werden. Die g�ngigen Punkte und Shortcuts lauten somit:

Bei Auswahl eines �Jahreszeiten�-Men�eintrages wird die Wahl, wie bereits bei den Gadgets besprochen, �ber die zentrale Funktion SetDatas() f�r alle Gadgets aktiviert. Neu in dieser Funktion ist, da� die aktuelle Auswahl �ber pOS_ SetWindowMenuChecker auch im Men� gesetzt wird.
Bei der Auswahl von �Quit� wird, wie nicht anders zu erwarten, das Programm beendet. Dabei k�nnte z.B. noch eine Abfrage eingebaut werden, ob das Programm wirklich beendet oder ob evtl. ver�nderte Daten noch gespeichert werden sollen.

Project-Men� weitere Men�s Edit-Men�
NewNeu (N)Help Hilfe (?)CutAusschneiden (X)
OpenLaden (O)CopyKopieren (C)
SaveSpeichern (S)PasteEinf�gen (V)
Save AsSpeichern unter (A)DeleteL�schen
PrintDrucken (P)UndoZur�cknehmen (Z)
InfoInformationRedoWiederherstellen
QuitBeenden (Q)
Bei �Information� wird ein EasyRequester (per pOS_EasyRequestArgs()) angezeigt, der die �blichen Angaben, wie z.B. Programmname, Versionsnummer, Erstellungsdatum, Copyrightvermerk etc. enth�lt. Interessant ist dabei, da� der Requester vom Typ ESYTYP_Info ist. Damit teilen Sie p.OS die Art des Requesters mit. Der Benutzer kann einstellen, welche Grafik zu welchem Requestertyp angezeigt wird. So kann man bereits ohne Lesen des Textes eine Gruppeneinteilung vornehmen. Typenlosen Requestern k�nnen Sie mit ESYTYP_GfxFile auch eine beliebige Grafik zuordnen. Dabei ist der Type auf ESYTYP_Std zu setzen. Dieser Typ ohne GfxFile zeigt nur den Text an. Eine Liste der m�glichen Typen und den Aufbau der zu �bergebenden pOS_EasyRequester-Struktur finden Sie unter �p:pIntui/ EasyReq.h�. EasyRequester sind unter p.OS aber nicht nur einfache R�ckfrage/Informations-Requester mit �Ok� oder �Weiter/Abbruch�, sie lassen sich vielmehr individuel programmieren. Man kann durchaus behaupten, da� EasyRequester vollwertige Fenster mit reduziertem Programmieraufwand erzeugen kann. Der Inhalt der Requester setzt sich n�mlich wieder � wie sollte es anders sein � aus Objekten zusammen. Durch Erg�nzen oder vollst�ndiges Ersetzen der normalen Textbox/Gadgetgruppe k�nnen Sie z.B. eine Texteingabe anfordern. Die notwendigen Tags zur Beschreibung des Fensterinhalts (z.B. einer eigenen Gadgetgruppe) finden Sie unter �p:pIntui/Easy Tags.h�.

Die normalen Requester haben aber einen Nachteil � sie arbeiten synchron. Die Funktion �pOS_EasyRequestArgs()� kehrt erst dann zur�ck, wenn der Benutzer ein Gadget aus dem Requester anklickt, bzw. (optional) eine Nachricht entsprechend der gesetzten IDCMP-Flags aufgetreten ist. W�hrend dieser Zeit kann Ihr Programm auch nicht auf Refresh-Anforderungen durch das OS reagieren. Hierbei zeigt sich aber der Vorteil, wenn das Fenster nur Gadgets enth�lt (z.B. auch f�r normale Textausgaben). Solche Gadgets k�nnen sich n�mlich unabh�ngig vom Programm selbst�ndig neu zeichnen und aufbauen.

Sollten Sie aber dennoch in die Situation kommen, da� w�hrend der Requesterausgabe das Programm weiterlaufen bzw. auf andere Nachrichten reagiert werden soll, existieren hierf�r drei Funktionen. Mit �pOS_CreateRequestWin()� erzeugen Sie das Fenster identisch wie bei synchronen Requestern. Dabei erhalten Sie einen pOS_Window-Zeiger, den Sie zum Schlie�en des Requesters an �pOS_DeleteRequestWin()� �bergeben m�ssen.

Einen normaler Messageloop k�nnte folgenderma�en aussehen:

 
ULONG sigs=pOS_WaitSignal(
         (1L < window->win_UserPort->mp_SigBit) |
         (1L < requester->win_UserPort->mp_SigBit) |
         DOSSIGF_CTRL_C);

Eine h�ufige Anwendung k�nnte aber auch sein, da� der EasyRequester nur einen Abbruch-Schalter enth�lt, mit der sich die aktuelle Berechnung durch das Programm vorzeitig beenden l��t. Dann m�ssen Sie regelm��ig mit �pOS_RequestWinHandler()� den Zustand des Requesters abfragen. Die Funktion erzeugt folgende Returnwerte:

2: es liegt keine Nachricht vor (nur wenn Handler-Wait auf FALSE gesetzt wurde)
1: ein gesetztes IDCMP-Ereignis ist eingetreten
0: Schalter ganz rechts (meist Abbruch) wurde angeklickt (bzw. einziger vorhandener)
gr��er 0: Schalterposition fortlaufend von links ab 1 gez�hlt

Beachten Sie, da� das Schlie�en des Requesters nicht automatisch geschieht, sondern mit �pOS_DeleteRequestWin()� erledigt werden mu�.
Wollen Sie den Requester mit einer Fortschrittsanzeige versehen, finden Sie das entsprechende Gadget �ObjATool_ProcessGadA.class� in der �ObjATool.library�.

Damit haben wir alle Komponenten f�r ein vollst�ndiges GUI-Programm zusammen: Windows, Gadgets, Men�s sowie deren Erzeugung und Auswertung. Der letzte Schritt sollte das Lokalisieren des Programms sein. Dabei wird das Amiga-kompatible Catalog-Konzept verwendet. Eine Catalog-Datei �ffnen Sie mit pOS_OpenCatalog() und schlie�en Sie am Programmende mit pOS_CloseCatalog(). Zur Laufzeit k�nnen Sie die Texte per pOS_GetCatalogStr() abfragen. Als letzten Parameter erwartet die Funktion einen Default-String, der zur�ckgegeben wird, wenn der Catalog nicht ge�ffnet werden konnte, bzw. wenn der String im Catalog fehlt. Vor oder nach Nutzung der Funktionen m�ssen Sie nat�rlich die �pLocale.library� �ffnen und schlie�en.

Die erste Aktion des Programms sollte das �ffnen der pLocale.library und des Catalogs sein. Dadurch kann auch die Template-Erkl�rung landesspezifisch erfolgen. F�r das Template sowie die im Programm fest eingebaute Sprache, empfehlen wir Englisch. Vor allem im Public Domain-Bereich kann durch die Catalog-Dateien eine gro�e (sprachenunabh�ngige) Verbreitung erfolgen. Es findet sich immer jemand, der f�r eine fehlende Sprache die Cataloge erg�nzt und somit das Programm noch mehr Benutzern zug�nglich macht. Dabei sollte man aber auch immer die Anleitungsdatei mit �bersetzen.

Auf die Lokalisierung eines Programms werden wir aber erst in lose folgenden, k�nftigen Kursteilen eingehen. Die Entwicklerunterlagen enthalten neben den Autodocs zu allen Libraries/Devices/Objekten auch jede Menge Beispielprogramme, die auf einzelne Funktionen eingehen. Bei weiteren Fragen k�nnen Sie sich direkt per E-Mail (�develop@ prodad.de�) an proDAD wenden. Mittlerweile existiert f�r p.OS auch eine Mailing-List, in der Sie als registrierter Entwickler Fragen und Erfahrungen weitergeben k�nnen.

bl


MagnaMedia Hauptseite

� Copyright by MagnaMedia Verlag AG, Haar bei M�nchen
Ver�ffentlichung und Vervielf�ltigung nur mit schriftlicher Genehmigung des Verlags


Kommentare, Fragen, Korrekturen und Kritik bitte an Webmaster AMIGA schicken.
Zuletzt aktualisiert am 06. August 1997.